package com.dragon.modules.yuegou.service.impl.coupon;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dragon.common.exception.DragonException;
import com.dragon.common.web.PageRequest;
import com.dragon.modules.yuegou.entity.busd.DistrictEntity;
import com.dragon.modules.yuegou.entity.coupon.CouponTemplateEntity;
import com.dragon.modules.yuegou.entity.coupon.MerchantCouponEntity;
import com.dragon.modules.yuegou.entity.merchant.MerchantQrcodeEntity;
import com.dragon.modules.yuegou.entity.merchant.UserEntity;
import com.dragon.modules.yuegou.entity.product.CoupApplyEntity;
import com.dragon.modules.yuegou.entity.product.CoupMerchantCouponEntity;
import com.dragon.modules.yuegou.entity.product.CoupTemplateEntity;
import com.dragon.modules.yuegou.entity.product.SkuEntity;
import com.dragon.modules.yuegou.enums.code.CouponCode;
import com.dragon.modules.yuegou.enums.coupon.ParkApplyStatus;
import com.dragon.modules.yuegou.enums.merchant.MerchantQrcodeStatus;
import com.dragon.modules.yuegou.mapper.coupon.MerchantCouponMapper;
import com.dragon.modules.yuegou.model.coupon.CouponTemplate;
import com.dragon.modules.yuegou.model.coupon.MerchantCoupon;
import com.dragon.modules.yuegou.model.coupon.ParkApply;
import com.dragon.modules.yuegou.query.coupon.MerchantCouponQuery;
import com.dragon.modules.yuegou.query.merchant.MerchantQrcodeQuery;
import com.dragon.modules.yuegou.service.busd.DistrictService;
import com.dragon.modules.yuegou.service.coupon.CouponTemplateService;
import com.dragon.modules.yuegou.service.coupon.MerchantCouponService;
import com.dragon.modules.yuegou.service.coupon.ParkApplyService;
import com.dragon.modules.yuegou.service.merchant.MerchantQrcodeService;
import com.dragon.modules.yuegou.service.merchant.UserService;
import com.dragon.modules.yuegou.service.product.CoupApplyService;
import com.dragon.modules.yuegou.service.product.CoupMerchantCouponService;
import com.dragon.modules.yuegou.service.product.CoupTemplateService;
import com.dragon.modules.yuegou.service.product.SkuService;
import com.dragon.modules.yuegou.web.Check;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 商户优惠券（商户购买优惠券，然后送给会员） 服务实现
 *
 * @author pbuilder generated
 * @date 2019-02-28 18:30:17
 * @version 2.0
 */
@Service("coupMerchantCouponService")
public class MerchantCouponServiceImpl
		extends ServiceImpl<MerchantCouponMapper, MerchantCouponEntity>
		implements MerchantCouponService {

	@Autowired
	private UserService merchantUserService;

	@Autowired
	private MerchantQrcodeService merchantQrcodeService;

	@Autowired
	private CouponTemplateService couponTemplateService;

	@Autowired
	private ParkApplyService parkApplyService;

	@Autowired
	private SkuService skuService;

	@Autowired
	private DistrictService districtService;

	@Autowired
	private CoupTemplateService coupTemplateService;

	@Autowired
	private CoupApplyService coupApplyService;

	@Autowired
	private CoupMerchantCouponService coupMerchantCouponService;

	@Override
	public MerchantCoupon createMerchantCoupon(String orderNo, String merchantUserId, MerchantCoupon coupon) {
		Check.notEmpty(merchantUserId, "merchantUserId is required");
		validateCreate(coupon);
		UserEntity merchantUser = merchantUserService.getById(merchantUserId);
		initCoupon(merchantUser, coupon);
		baseMapper.insert(coupon);
		return coupon;
	}

	@Override
	@Transactional
	public List<MerchantCoupon> bachCreateCoupon(String orderNo, String merchantUserId, List<MerchantCoupon> coupons) {
		Check.notEmpty(merchantUserId, "merchantUserId is required");
		Check.notEmpty(coupons, "coupons must not empty");
		UserEntity merchantUser = merchantUserService.getById(merchantUserId);
		coupons.forEach(coupon -> {
			initCoupon(merchantUser, coupon);
			coupon.setCreatedBy(merchantUserId);
		});
		coupons.stream().forEach(coupon ->{
			this.validateCreate(coupon);
			save(coupon);
		});
		return coupons;
	}

	/**
	 * 验证创建商户优惠券的合法性
	 * 
	 * @param coupon 商户优惠券
	 */
	private void validateCreate(MerchantCoupon coupon) {
		Check.notNull(coupon, "coupon is required");
		Check.notEmpty(coupon.getMerchantId(), "coupon.merchantId is required");
		Check.notEmpty(coupon.getCouponTemplateId(), "coupon.couponTemplateId is required");
		Check.positive(coupon.getTotal(), "coupon.total must positive");
	}

	/**
	 * 初始化商户优惠券
	 * 
	 * @param coupon 商户优惠券
	 */
	private void initCoupon(UserEntity merchantUser, MerchantCoupon coupon) {
		coupon.setMerchantId(merchantUser.getMerchantId());
		coupon.setStock(coupon.getTotal());
		coupon.setGranted(0);
		coupon.setVersion(1);
	}

	@Override
	public String grantQRcode(String merchantCouponId) {
		MerchantQrcodeQuery query = new MerchantQrcodeQuery();
		query.merchantCouponId().eq(merchantCouponId);
		query.status().eq(MerchantQrcodeStatus.READY);
		IPage<MerchantQrcodeEntity> page = new Page<>(1,50,false);
		IPage<MerchantQrcodeEntity> pageData = merchantQrcodeService.page(page, query.toQueryWrapper());
        List<MerchantQrcodeEntity> list = pageData.getRecords();
        if (CollectionUtils.isNotEmpty(list)) {
            int rValue = RandomUtils.nextInt(0, list.size());
            return list.get(rValue).getId();
        }
		throw new DragonException(CouponCode.MERCHANT_COUPON_APPLY_ISNULL);
	}

	@Override
	public IPage<MerchantCoupon> couponRecords(PageRequest page, String merchantId) {
		IPage<MerchantCoupon> iPage = new Page<>(page.getPage(),page.getSize(),false);
		IPage<MerchantCoupon> ipage = baseMapper.merchantApplyParkCoupon(iPage,merchantId);
		ipage.getRecords().stream().forEach(this::fillCouponTemplate);
		return ipage;
	}

	@Override
	public IPage<MerchantCoupon> yshAppCouponRecords(PageRequest page, String merchantId) {
		IPage<MerchantCoupon> iPage = new Page<>(page.getPage(),page.getSize(),false);
		IPage<MerchantCoupon> ipage = baseMapper.yshAppMerchantApplyParkCoupon(iPage,merchantId);
		ipage.getRecords().stream().forEach(this::fillYshAppCouponTemplate);
		return ipage;
	}

	@Override
	public IPage<MerchantCoupon> merchantGrantList(PageRequest page,String merchantId) {
		IPage<MerchantCoupon> iPage = new Page<>(page.getPage(),page.getSize(),false);
		IPage<MerchantCoupon> ipage = baseMapper.merchantGrantList(iPage,merchantId);
		ipage.getRecords().stream().forEach(this::fillMerchantGrantListCouponTemplate);
		return ipage;
	}


	/**
	 * 给发放停车券填充优惠券模板属性
	 * @param merchantCoupon
	 */
	private void fillMerchantGrantListCouponTemplate(MerchantCoupon merchantCoupon) {
		ParkApply apply = parkApplyService.getApply(merchantCoupon.getParkApplyId());
		MerchantQrcodeQuery qrcodeQuery = new MerchantQrcodeQuery();
		qrcodeQuery.merchantCouponId().eq(merchantCoupon.getId());
		qrcodeQuery.status().eq(MerchantQrcodeStatus.READY);
		Long count = merchantQrcodeService.count(qrcodeQuery.toQueryWrapper());
		merchantCoupon.setStock(count.intValue());
		merchantCoupon.setGranted(merchantCoupon.getTotal() - count.intValue());

		SkuEntity sku = skuService.getById(apply.getSkuId());

		CouponTemplateEntity couponTemplate = couponTemplateService.getById(merchantCoupon.getCouponTemplateId());
		if (null != couponTemplate) {
			CouponTemplate template = new CouponTemplate(couponTemplate);
			template.setTitle(sku.getTitle());
			template.setStartTime(apply.getCheckBeginTime());
			template.setEndTime(apply.getCheckEndTime());
			merchantCoupon.setCouponTemplate(template);
		}
	}

	/**
	 * 给发放停车券填充优惠券模板属性
	 * @param merchantCoupon
	 */
	private void fillYshAppCouponTemplate(MerchantCoupon merchantCoupon) {
		ParkApply apply = parkApplyService.getApply(merchantCoupon.getParkApplyId());
		MerchantQrcodeQuery qrcodeQuery = new MerchantQrcodeQuery();
		qrcodeQuery.merchantCouponId().eq(merchantCoupon.getId());
		qrcodeQuery.status().eq(MerchantQrcodeStatus.READY);
		Long count = merchantQrcodeService.count(qrcodeQuery.toQueryWrapper());
		merchantCoupon.setStock(count.intValue());
		merchantCoupon.setGranted(merchantCoupon.getTotal() - count.intValue());
		SkuEntity sku = skuService.getById(apply.getSkuId());

		CouponTemplateEntity couponTemplate = couponTemplateService.getById(merchantCoupon.getCouponTemplateId());
		if (null != couponTemplate) {
			CouponTemplate template = new CouponTemplate(couponTemplate);
			BeanUtils.copyProperties(couponTemplate, template);
			template.setTitle(sku.getTitle());
			template.setStartTime(apply.getCheckBeginTime());
			template.setEndTime(apply.getCheckEndTime());
			merchantCoupon.setCouponTemplate(template);
			
			String busdId = couponTemplate.getBusdId();
			DistrictEntity district = districtService.getById(busdId);
			merchantCoupon.setDistrictName(district.getBcName());
		}
	}

	/**
	 * 给发放停车券填充优惠券模板属性
	 * @param merchantCoupon
	 */
	private void fillCouponTemplate(MerchantCoupon merchantCoupon) {
		ParkApply apply = parkApplyService.getApply(merchantCoupon.getParkApplyId());
		MerchantQrcodeQuery qrcodeQuery = new MerchantQrcodeQuery();
		qrcodeQuery.merchantCouponId().eq(merchantCoupon.getId());
		qrcodeQuery.status().eq(MerchantQrcodeStatus.READY);
		Long count = merchantQrcodeService.count(qrcodeQuery.toQueryWrapper());
		merchantCoupon.setStock(count.intValue());
		merchantCoupon.setGranted(merchantCoupon.getTotal() - count.intValue());

		SkuEntity sku = skuService.getById(apply.getSkuId());

		CouponTemplateEntity couponTemplate = couponTemplateService.getById(merchantCoupon.getCouponTemplateId());
		if (null != couponTemplate) {
			CouponTemplate template = new CouponTemplate(couponTemplate);
			template.setTitle(sku.getTitle());
			template.setStartTime(apply.getCheckBeginTime());
			template.setEndTime(apply.getCheckEndTime());
			merchantCoupon.setCouponTemplate(template);
		}
	}

	@Override
	public MerchantCoupon showGiveCode(String merchantCouponId) {
		MerchantCouponEntity coupon = getById(merchantCouponId);
		if (StringUtils.isNotEmpty(coupon.getParkApplyId())) {
			return showGiveCodeByParkApply(coupon.getParkApplyId());
		}
		String qrcodeUrl = this.grantQRcode(merchantCouponId);
		MerchantCoupon merchantCoupon = new MerchantCoupon();
		merchantCoupon.setQrcodeUrl(qrcodeUrl);
		return merchantCoupon;
	}

	@Override
	public MerchantCoupon showGiveCodeByParkApply(String parkApplyId) {
		ParkApply parkApply = parkApplyService.getApply(parkApplyId);
		if (parkApply == null) {
			throw new DragonException(CouponCode.MERCHANT_COUPON_APPLY_NOT_FIND);
		}
		// 判断是否已支付
		if (parkApply.getStatus() != ParkApplyStatus.PAYED) {
			throw new DragonException(CouponCode.NOT_PAYED);
		}

		// 还未到停车券的发放开始时间
		if (LocalDateTime.now().isBefore(parkApply.getCheckBeginTime())) {
			throw new DragonException(CouponCode.LESS_THAN_BEGIN_TIME);
		}

		// 已经超出了停车券的开始结束时间
		if (LocalDateTime.now().isAfter(parkApply.getCheckEndTime())) {
			throw new DragonException(CouponCode.MERCHANT_COUPON_APPLY_EXPRIED);
		}
		MerchantCouponQuery query = new MerchantCouponQuery();
		query.parkApplyId().eq(parkApplyId);
		List<MerchantCouponEntity> list = list(query.toQueryWrapper());
		MerchantCoupon coupon = new MerchantCoupon();
		if (CollectionUtils.isNotEmpty(list)) {
			coupon = new MerchantCoupon(list.get(0));
			String qrcodeUrl = this.grantQRcode(coupon.getId());
			coupon.setQrcodeUrl(qrcodeUrl);
		}
		
		SkuEntity sku = skuService.getById(parkApply.getSkuId());
		coupon.setTitle(sku.getTitle());
		DistrictEntity district = districtService.getById(parkApply.getBusdId());
		coupon.setDistrictName(district.getBcName());
		coupon.setEndTime(parkApply.getEndTime());
		return coupon;
	}

	@Override
	public MerchantCoupon getGrantQRcode(String merchantCouponId, Integer type) {
		MerchantCoupon coupon = new MerchantCoupon();
		if (type != 1) {
			MerchantCouponEntity entity = getById(merchantCouponId);
			if (StringUtils.isNotEmpty(entity.getParkApplyId())) {
				return showGiveCodeByParkApply(entity.getParkApplyId());
			}
			coupon = new MerchantCoupon(entity);
		} else {
			CoupMerchantCouponEntity byId = coupMerchantCouponService.getById(merchantCouponId);
			CoupApplyEntity coupApply = coupApplyService.getById(byId.getCoupApplyId());
			CoupTemplateEntity template = coupTemplateService.getById(coupApply.getCoupTemplateId());
			coupon.setTitle(template.getTitle());
			coupon.setGranted(coupApply.getReleasedQuantity());
			coupon.setTotal(coupApply.getCheckQuantity());
			coupon.setEndTime(coupApply.getCheckEndTime());
			DistrictEntity district = districtService.getById(template.getBusdId());
			coupon.setDistrictName(district.getBcName());
		}
		String qrcodeUrl = this.grantQRcode(merchantCouponId);
		coupon.setQrcodeUrl(qrcodeUrl);
		return coupon;
	}
}